package com.shelpe.services.simbasync.service.impl;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang.math.NumberUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.shelpe.services.simbasync.dao.AdgroupsMapper;
import com.shelpe.services.simbasync.dao.RptAdgroupMapper;
import com.shelpe.services.simbasync.exception.ApiException;
import com.shelpe.services.simbasync.model.Adgroups;
import com.shelpe.services.simbasync.model.AdgroupsExample;
import com.shelpe.services.simbasync.model.Products;
import com.shelpe.services.simbasync.model.RptAdgroup;
import com.shelpe.services.simbasync.model.RptAdgroupExample;
import com.shelpe.services.simbasync.service.AdgroupsService;
import com.shelpe.services.simbasync.service.ProductsService;
import com.shelpe.services.simbasync.util.Util;


@Service

public class AdgroupsServiceImpl implements AdgroupsService {

	private static final Logger logger = LoggerFactory.getLogger(AdgroupsServiceImpl.class);
	
	@Autowired
	private AdgroupsMapper mapper;
	
	@Autowired
	private RptAdgroupMapper rptmapper;
	
	@Autowired
	private ProductsService product;
	
	@Autowired
	private PlatformTransactionManager txManager;
	
	@Override
	public int countAll(){
		
		AdgroupsExample example = new AdgroupsExample();
		
		return mapper.countByExample(example);
	}
	
	@Override
	public int countByUserId(long userId){
		
		AdgroupsExample example = new AdgroupsExample();
		example.createCriteria().andUserIdEqualTo(userId);
		
		return mapper.countByExample(example);
	}
	
	@Override
	public int addAdgroups(Adgroups ad) {//存在的话不需要加入
		// TODO Auto-generated method stub
		return mapper.insert(ad);
	}

	@Override
	public int addAdgroupsList(List<Adgroups> adList) {
		// TODO Auto-generated method stub
		int num = 0;
		for(Adgroups item : adList){
			num += mapper.insert(item);
		}
		return num;
	}

	@Override
	public int deleteRptAdgroupsByDateRange(List<Long> adgroupIds, Date startDate, Date endDate){
		RptAdgroupExample example = new RptAdgroupExample();
		example.createCriteria()
		.andDateBetween(startDate, endDate)
		.andAdgroupIdIn(adgroupIds);
		
		return rptmapper.deleteByExample(example);
	}
	
	@Override
	public int addRptAdgroups(RptAdgroup rpt) {
		// TODO Auto-generated method stub
		return rptmapper.insert(rpt);
	}

	@Override
	public int addRptAdgroupsList(List<RptAdgroup> rptList) {
		// TODO Auto-generated method stub
		int num = 0;
		for(RptAdgroup rpt : rptList){
			num += rptmapper.insert(rpt);
		}
		return num;
	}
	
	@Override
	public int insertAdgroupsBatch(List<Adgroups> adList){
		
		int num = 0;
		
		if(adList == null || adList.size() == 0){
			return num;
		}
		
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

		TransactionStatus status = txManager.getTransaction(def);

		
		try{
			
			num = mapper.insertBatch(adList);
			
		}catch(Exception e){
			
			  txManager.rollback(status);
			  throw e;
		}
		
		txManager.commit(status);
		
		return num;
	}
	
	@Override
	public int insertRptAdgroupsBatch(List<RptAdgroup> rptList){
		int num = 0;
		
		int pageSize = 15000;
		if(rptList != null && rptList.size() > 0){
			int fromIndex = 0;
			int endIndex = 0;
			do{
				endIndex += pageSize; 
				if(endIndex > rptList.size()){
					endIndex = rptList.size();
				}
				num += rptmapper.insertBatch(rptList.subList(fromIndex, endIndex));	
				fromIndex += pageSize; 
			
			}while(fromIndex < rptList.size());
			
		}
		
		return num;
	}
	
	@Override
	public Adgroups getAdgroupsById(long adgroupId){
		
		return mapper.selectByPrimaryKey(adgroupId);
	}
	@Override
	public List<Adgroups> parseJsonToAdgroups(String response) {
		// TODO Auto-generated method stub
		List<Adgroups> list = new ArrayList<Adgroups>();
		
		if(response != null && response.contains("simba_adgroupsbycampaignid_get_response")){
			
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("simba_adgroupsbycampaignid_get_response");
			JSONObject objItems = objRes==null? null : objRes.getJSONObject("adgroups");
			JSONObject objList = objItems==null? null : objItems.getJSONObject("adgroup_list");
			JSONArray jsonList = objList==null? null : objList.getJSONArray("a_d_group");

			int size = jsonList == null? 0 : jsonList.size();
		
			for(int i = 0; i < size; i++){
				JSONObject item = jsonList.getJSONObject(i);
				//解析
				Adgroups ad = new Adgroups();
				ad.setAdgroupId(item.getLong("adgroup_id"));
				ad.setCampaignId(item.getLong("campaign_id"));
				ad.setCategoryIds(item.getString("category_ids"));
				ad.setCreateTime(item.getDate("create_time"));
				ad.setDefaultPrice(item.getInteger("default_price"));
				ad.setModifiedTime(item.getDate("modified_time"));
				ad.setNick(item.getString("nick"));
				ad.setNumIid(item.getLong("num_iid"));
				ad.setOfflineType(item.getString("offline_type"));
				ad.setOnlineStatus(item.getString("online_status"));
				String reason = item.getString("reason");
				reason = reason == null ? "" : reason;
				ad.setReason(reason);
				Integer nonsearchMaxPrice = item.getInteger("nonsearch_max_price");
				nonsearchMaxPrice = nonsearchMaxPrice == null ? 0 : nonsearchMaxPrice;
				ad.setNonsearchMaxPrice(nonsearchMaxPrice);
				Byte nonsearchStatus = item.getByte("nonsearch_status");
				nonsearchStatus = nonsearchStatus == null ? 0 : nonsearchStatus;
				ad.setIsNonsearchMaxPrice(nonsearchStatus);
				ad.setImgUrl(item.getString("img_url"));
				ad.setTitle(item.getString("title"));	
				ad.setMobileDiscount(item.getFloat("mobile_discount"));
				
				ad.setItemImgs("");
				ad.setProductProps("");
				ad.setProductType("");
				
				list.add(ad);
			}	
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is parseJsonToAdgroups, response: {}", response);
			throw new ApiException();
		}
		
		return list;
	}
	
	@Override
	public void updateAdgroupsData(long userId, List<Adgroups> adList){
		
		Date updateDate = new Date();
		
		String lastDateStr = "1970-01-01 00:00:00";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		for(Adgroups ad : adList){
			
			Products pro = product.getItemById(ad.getNumIid());
			if(pro!=null){
				ad.setItemImgs(pro.getItemImgs());
				ad.setProductProps(pro.getProps());
				ad.setProductType(pro.getType());
			}
			
			ad.setUserId(userId);
			ad.setUpdatedTime(updateDate);
			ad.setPlaceId("");//位置id
			ad.setDriveType(Byte.valueOf("0"));//开车类型
			ad.setStatus(Byte.valueOf("0")); //开车状态
			try {
				ad.setMaintainedDate(sdf.parse(lastDateStr));
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	@Override
	public List<Adgroups> getAdgroupsByCampaignId(long campaignId) {
		// TODO Auto-generated method stub
		AdgroupsExample example = new AdgroupsExample();
		example.createCriteria().andCampaignIdEqualTo(campaignId);

		return mapper.selectByExample(example);
	}
	
	@Override
	public List<Adgroups> getAdgroupsByUserId(long userId){
		
		AdgroupsExample example = new AdgroupsExample();
		example.createCriteria().andUserIdEqualTo(userId);
		
		return mapper.selectByExample(example);
	}

	@Override
	public Map<String, List<Adgroups> > splitAdgroups(List<Adgroups> newList, List<Adgroups> oldList) {
		
		Map<String, List<Adgroups> > ret = new HashMap<String, List<Adgroups> >();
		List<Adgroups> updated = new ArrayList<Adgroups>();
		List<Adgroups> deleted = new ArrayList<Adgroups>();
		List<Adgroups> added = new ArrayList<Adgroups>();
		Set<Long> newAdIds = new HashSet<Long>();
		int oldSize = oldList == null? 0 : oldList.size();
		int i = 0;
		
		String lastDateStr = "1970-01-01 00:00:00";
		SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		
		for(Adgroups newItem : newList){
			
			for(i = 0; i < oldSize; i++){
				Adgroups oldItem = oldList.get(i);
				if(newItem.getAdgroupId().equals(oldItem.getAdgroupId())){
					//比较其他字段是否相同
					if(!isEqualAdgroups(newItem, oldItem)){
						if(oldItem.getDriveType() != null){
							newItem.setDriveType(oldItem.getDriveType());
						}
						if(oldItem.getStatus() != null){
							newItem.setStatus(oldItem.getStatus());
						}
						
						Date newMaintainDate = new Date();
						try {
							newMaintainDate = sdf.parse(lastDateStr);
						} catch (ParseException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						if(oldItem.getMaintainedDate() != null){
							newMaintainDate = oldItem.getMaintainedDate();
						}
						newItem.setMaintainedDate(newMaintainDate);
						updated.add(newItem);
					}
					break;
				}
			}
			if(i == oldSize){
				added.add(newItem);
			}
			newAdIds.add(newItem.getAdgroupId());
		}
		
		for(Adgroups oldItem : oldList){
			if(!newAdIds.contains(oldItem.getAdgroupId())){
				deleted.add(oldItem);
			}
		}
		ret.put("delete", deleted);	
		ret.put("update", updated);	
		ret.put("add", added);	
				
		return ret;
	}
	
	/**
	 * 这里的相等是指，会变动的属性值是否有修改
	 * 
	 * */
	private boolean isEqualAdgroups(Adgroups newAd, Adgroups oldAd){
		
		if(newAd.getModifiedTime().getTime() == oldAd.getModifiedTime().getTime() && 
				newAd.getItemImgs().equals(oldAd.getItemImgs()) &&
				newAd.getProductProps().equals(oldAd.getProductProps()) &&
				newAd.getProductType().equals(oldAd.getProductType()) ){
			return true;
		}
		
		return false;
	}

	@Override
	public int deleteAdgroups(Adgroups ad) {
		// TODO Auto-generated method stub
		return mapper.deleteByPrimaryKey(ad.getAdgroupId());
	}

	@Override
	public int deleteAdgroupsList(List<Adgroups> adList) {
		// TODO Auto-generated method stub
		int num = 0;
		for(Adgroups ad : adList){
			num += deleteAdgroups(ad);
		}
		return num;
	}

	@Override
	public int updateAdgroups(Adgroups ad) {
		// TODO Auto-generated method stub
		return mapper.updateByPrimaryKeyWithBLOBs(ad);
	}

	@Override
	public int updateAdgroupsList(List<Adgroups> adList) {
		// TODO Auto-generated method stub
		int num = 0;
		for(Adgroups ad : adList){
			num += updateAdgroups(ad);
		}
		return num;
	}

	@Override
	public List<RptAdgroup> parseJsonToRptAdgroupsBase(String response) {
		// TODO Auto-generated method stub
		List<RptAdgroup> ret = new ArrayList<RptAdgroup>();
		
		if(response != null && response.contains("simba_rpt_adgroupbase_get_response")){
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("simba_rpt_adgroupbase_get_response");
			JSONArray jsonList = objRes==null? null : objRes.getJSONArray("rpt_adgroup_base_list");
			
			int size = jsonList == null? 0 : jsonList.size();
			
			for(int i = 0; i < size; i++){
				JSONObject item = jsonList.getJSONObject(i);
				RptAdgroup rpt = new RptAdgroup();
				
				int impression = NumberUtils.toInt(item.getString("impressions"), 0);
				int cost = NumberUtils.toInt(item.getString("cost"), 0);
				int click = NumberUtils.toInt(item.getString("click"), 0);
				float ctr = NumberUtils.toFloat(item.getString("ctr"), 0.0f);
				float cpc = NumberUtils.toFloat(item.getString("cpc"), 0.0f);
				float cpm = NumberUtils.toFloat(item.getString("cpm"), 0.0f);
				float avgpos = NumberUtils.toFloat(item.getString("avgpos"), 0.0f);
				
				rpt.setCpc(cpc);
				rpt.setCtr(ctr) ;
				rpt.setImpressions(impression) ;
				rpt.setCpm(cpm);
				rpt.setClick(click);
				rpt.setCost(cost) ;
				rpt.setAdgroupId(item.getLong("adgroupId"));
				rpt.setCampaignId(item.getLong("campaignId"));
				rpt.setDate(item.getDate("date"));
				rpt.setSearchType(item.getByte("searchtype"));
				rpt.setSource(item.getByte("source"));
				rpt.setAvgpos(avgpos);
				
				//初始化以下值
				rpt.setDirectPay(0);
				rpt.setIndirectPay(0); 
				rpt.setDirectPayCount(0);
				rpt.setIndirectPayCount(0);
				rpt.setFavShopCount(0);
				rpt.setFavItemCount(0); 	
				
				ret.add(rpt);
			}
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is parseJsonToRptAdgroupsBase, response: {}", response);
			throw new ApiException();
		}
		
		return ret;
	}

	@Override
	public Date getLastTimeFromRpt(long userId, long campaignId, long adgroupId) {
		// TODO Auto-generated method stub
		return rptmapper.getLastTimeFromRpt(userId, campaignId, adgroupId);
	}

	@Override
	public int combineRptAdgroupsEffect(String response, Map<String, Integer> lastDayRecord, List<RptAdgroup> list) {
		// TODO Auto-generated method stub
		int size = 0;
		int lastDayRecordTotal = 0;
		int lastDayNoDataNum = 0;
		if(response != null && response.contains("simba_rpt_adgroupeffect_get_response")){
			JSONObject object = JSON.parseObject(response);
			JSONObject objRes = object==null? null : object.getJSONObject("simba_rpt_adgroupeffect_get_response");
			JSONArray jsonList = objRes==null? null : objRes.getJSONArray("rpt_adgroup_effect_list");
			size = jsonList == null? 0 : jsonList.size();
			Date lastDay = Util.getLastDayYYYYMMDD();
			
			for(int i = 0; i < size; i++){
				JSONObject item = jsonList.getJSONObject(i);
				
				if(item.getDate("date").getTime() == lastDay.getTime()){//前一天的数据会出现这种情况
					lastDayRecordTotal++;
					if(!(item.containsKey("indirectpay") || item.containsKey("favItemCount") || item.containsKey("indirectpaycount") ||
							item.containsKey("favShopCount") || item.containsKey("directpay") || item.containsKey("directpaycount"))){
						//这些都没有，认为没有数据，
						lastDayNoDataNum++;
						continue;
					}
				}
				
				int indirectpay = NumberUtils.toInt(item.getString("indirectpay"), 0);
				int	favItemCount = NumberUtils.toInt(item.getString("favItemCount"), 0);
				int	indirectpaycount = NumberUtils.toInt(item.getString("indirectpaycount"), 0);
				int	favShopCount = NumberUtils.toInt(item.getString("favShopCount"), 0);
				int	directpay = NumberUtils.toInt(item.getString("directpay"), 0);
				int	directpaycount = NumberUtils.toInt(item.getString("directpaycount"), 0);
			
				//根据key找到相关的
				for(RptAdgroup rpt : list){
					if(rpt.getAdgroupId().equals(item.getLong("adgroupId")) &&
							rpt.getCampaignId().equals(item.getLong("campaignId")) &&
							rpt.getSource().equals(item.getByte("source")) &&
							rpt.getSearchType().equals(item.getByte("searchtype")) && 
							rpt.getDate().getTime() == item.getDate("date").getTime()){

						rpt.setDirectPay(directpay);
						rpt.setIndirectPay(indirectpay); 
						rpt.setDirectPayCount(directpaycount);
						rpt.setIndirectPayCount(indirectpaycount);
						rpt.setFavShopCount(favShopCount);
						rpt.setFavItemCount(favItemCount); 	
						
						break;
					}
				}		
			}
		}else{
			logger.warn("can not get any info from proxy, maybe something is wrong, api is combineRptAdgroupsEffect, response: {}", response);
			throw new ApiException();
		}
		lastDayRecord.put("total", lastDayRecordTotal);
		lastDayRecord.put("lost", lastDayNoDataNum);
		
		return size;
	}
	
	@Override
	public void updateRptAdgroupsData(long userId, List<RptAdgroup> list){
		
		for(RptAdgroup rpt : list){
			rpt.setTaobaoUserId(userId);
		}
		//extra data
	}
}